package es.uji.viselab.experiment;

import java.awt.Button;
import java.awt.Dialog;
import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.TextArea;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileInputStream;
import java.io.IOException;

import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import es.uji.viselab.BenchMarkingSystem;
import es.uji.viselab.ViSeLabException;
import es.uji.viselab.ComponentsConfiguration;
import es.uji.viselab.benchmark.database.DBConnection;
import es.uji.viselab.benchmark.database.DBConnectionMySQL;
import es.uji.viselab.image.process.CameraParameters;
import es.uji.viselab.image.process.ImageProcessing;
import es.uji.viselab.image.source.ImageCameraSimulated;
import es.uji.viselab.image.source.ImageListener;
import es.uji.viselab.math.Vector3;
import es.uji.viselab.robot.Robot;
import es.uji.viselab.robot.RobotCatalog;
import es.uji.viselab.robot.SimulatedRobot;
import es.uji.viselab.sceneview.SceneView;
import es.uji.viselab.sceneview.SimpleRobotScene;
import es.uji.viselab.task.NetworkTaskLink;
import es.uji.viselab.visualservoing.IBVS;
import es.uji.viselab.visualservoing.VisualServoingListener;
import es.uji.viselab.visualservoing.VisualServoingTask;

public class ExperimentLoopTask extends ExperimentInterface implements ActionListener  {



	protected Button buttonLoadFile = new Button("Load from file");
	protected Button buttonDoSomething = new Button("Do something");

	protected TextArea textLog = new TextArea(10, 60);
	FileDialog fileDialog;
	protected JPanel rootPanel;

	private Experiment experiment;

	/*public ExperimentLoopTask(NetworkTaskLink tl, BenchMarkingSystem bm) {
	//	super(tl, bm);
		constructPanel();
	}*/

	public ExperimentLoopTask(BenchMarkingRecorder bm) {
	   	super(bm);
		// Here are the experiment parameters
		experiment = new Experiment1();
		constructPanel();
	}

	public ExperimentLoopTask() {
		super();
		constructPanel();
	}

	protected void constructPanel() {

		rootPanel = new JPanel();
		rootPanel.setLayout(new BoxLayout(rootPanel, BoxLayout.PAGE_AXIS));

		JPanel line1 = new JPanel();
		line1.setLayout(new FlowLayout());
		((FlowLayout) line1.getLayout()).setAlignment(FlowLayout.CENTER);
		line1.add(buttonLoadFile);
		line1.add(buttonDoSomething);

		JPanel line2 = new JPanel();
		line2.setLayout(new FlowLayout());
		((FlowLayout) line2.getLayout()).setAlignment(FlowLayout.CENTER);
		line2.add(textLog);

		buttonLoadFile.addActionListener(this);
		buttonDoSomething.addActionListener(this);

		rootPanel.add(line1);
		rootPanel.add(line2);

	}

	public JPanel getPanel() {

		return rootPanel;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource().equals(buttonDoSomething)) {
			try {
				runTestingTask();
			} catch (ViSeLabException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		}
		if (e.getSource().equals(buttonLoadFile)) {
			loadFile();
		}
	}

	private void runTestingTask() throws ViSeLabException {

		
		
		// Create the robot, it will be a flying end-effector robot
		Robot robot = new SimulatedRobot(RobotCatalog.FLYING_CAMERA);

		// This is the scene to see the robot and camera, it has not any other
		// functionality
		SceneView scene = new SimpleRobotScene(experiment);
		showPanel(scene.getPanel(), ComponentsConfiguration.SCENE);
		robot.addListener(scene); // Robot --> Scene

		// This are the real 3D feature points
		Vector3[] points = experiment.getModel3d();
		scene.plot(points);

		// Now, the camera can be created and its panel showed
		ImageProcessing image = new ImageCameraSimulated(experiment);
		showPanel(image.getPanel(), ComponentsConfiguration.CAMERA_SIMULATED);
		robot.addListener(image); // Robot --> Camera (Image)

		// The benchmarking system, will store everything, 
		// to later show the results
		DBConnection db = new DBConnectionMySQL();
		benchmarking.setDatabase(db);
		image.addListener(benchmarking); // Camera (Image) --> Benchmarking System


		
		VisualServoingTask visualServoing = new IBVS();
		// experiment --> Visual Servoing
		experiment.setVisualServoing(visualServoing);

		// experiment --> Benchmarking System
		experiment.setBenchmarkingSystem(benchmarking);
		
      	// Camera (Image) --> experiment
		image.addListener(experiment);

		// experiment --> Robot
		experiment.setRobot(robot);

		/*
		 * Now the control loop is closed:
		 * 
		 * Robot -> Camera -> Task -> VS -> Task -> Robot
		 * 
		 * The Bencharking system is "in the middle" only to gather data the
		 * "Task" has the control to stop the loop, otherwise, it lets to
		 * continue
		 * 
		 */

		// This triggers everything thanks to the events chain
		experiment.Start();

	}

	

	private void loadFile() {
		JFrame frame = new JFrame();
		frame.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		frame.setSize(525, 325);
		// frame.setVisible(true);
		Dialog dialog = new Dialog(frame);
		fileDialog = new FileDialog(dialog, "Select File to Open");
		fileDialog.setVisible(true);
		System.out.println(fileDialog.getDirectory() + fileDialog.getFile());
		load(fileDialog.getDirectory() + fileDialog.getFile());
	}

	public void load(String fname) { // this method is for reading a file
		try {
			FileInputStream fis1 = new FileInputStream(fname);
			int fileSize = fis1.available();
			byte buf1[] = new byte[fileSize];
			fis1.read(buf1);
			String str1 = new String(buf1);
			System.out.println(str1);
			fis1.close();
		} catch (IOException e) {
			System.exit(0);
		}
	}
	
	private void showPanel(JPanel p, ComponentsConfiguration component) {
		Window topWindow = SwingUtilities.getWindowAncestor(rootPanel);
		JDialog dialog = new JDialog(topWindow, component.getTitle(), ModalityType.MODELESS);
		dialog.getContentPane().add(p);
		dialog.pack();
		dialog.setLocationRelativeTo(topWindow);
		dialog.setSize(component.getWidth(), component.getHeight());
		dialog.setVisible(true);
	}

}
